<?php

namespace app\components;

use Yii;
use app\exception\LogException;
use app\events\LogEvent;
use app\behaviors\LogBehavior;
use yii\behaviors\SluggableBehavior;
/**
 * 日志组件
 * @author 胖子
 * @since 1.0
 */
class LogComponent extends BaseComponent{

    public $title = '';
	const EVENT_BEFORE_LOG = 'beforeLog';
	const EVENT_AFTER_LOG = 'afterLog';

	/**
	 * 日志级别集合
	 */
	const LEVELS = ['info','warn','error','trace','debug'];
	/**
	 * 日志类型集合
	 */
	const CATES = ['app','cmd','api','curl','other'];
	/**
	 * @var string 平台名称
	 */
	public $app = 'ulog';
	/**
	 * @var string 日志级别
	 */
	private $_level = 'info';
	/**
	 * @var string 日志分类
	 */
	private $_cate = 'app';
	/**
	 * @var string 日志格式
	 */
	public $format = '';
	/**
	 * @var mixed 日志前缀
	 */
	public $prefix = '';
	/**
	 * @var mixed 日志后缀
	 */
	public $suffix = '';
    /**
     * @var string 日志分类
     */
    private $_lastLog = 'app';

	/**
	 * 初始化方法
	 * @return [type] [description]
	 */
	public function init()
    {
        parent::init();


    }

	/**
	 * 写日志方法
	 * @param  string $msg 日志内容
	 */
    public function log (string $msg, string $level = '', string $cate = ''){
    	$level or $level = $this->_level;
    	$cate or $cate = $this->_cate;

        if(!in_array($this->_level, self::LEVELS)){
            throw new LogException('未知的异常级别:'.$this->_level, 1);
        }
        if(!in_array($this->_cate, self::CATES)){
            throw new LogException('未知的异常分类'.$this->_cate, 1);
        }

    	$prefix = $this->getPrefix($level, $cate);
    	$suffix = $this->getSuffix();

        $log = $prefix.$msg.$suffix;
        $event =  new LogEvent([
            'log' => $log,
            'level' => $level,
            'cate' => $cate,
        ]);
        $this->trigger(self::EVENT_BEFORE_LOG, $event);
        // $this->trigger(self::EVENT_BEFORE_LOG);
        $this->HandlLog($log);
        $this->trigger(self::EVENT_AFTER_LOG);
        $this->_lastLog = $log;
    }

    protected function HandlLog($log){
        echo $log, PHP_EOL;
    }
    /**
     * 获取日志前缀
     * @return string 日志前缀
     */
    protected function getPrefix(string $level, string $cate) : string {
    	$prefix = '';
    	if(is_string($this->prefix)){
    		$prefix = $this->prefix;
    	}elseif(is_callable($this->prefix)){
    		$prefix = ($this->prefix)();
    	}
		return date('[Y-m-d H:i:s]'). "[{$this->app}][" . $this->getIp() . "][$cate][$level] " . $prefix;
    }

    /**
     * 获取日志后缀
     * @return string 日志后缀
     */
    protected function getSuffix(){
    	if(is_string($this->suffix)){
    		return $this->suffix;
    	}elseif(is_callable($this->suffix)){
    		return ($this->suffix)();
    	}else{
    		return '';
    	}
    }
    /**
     * 设置错误界别
     * @param  string $level 日志界别
     * @return obj           对象本身
     */
    public function level($level){
        if(in_array($level, self::LEVELS)){
            $this->_level = $level;
        }
        return $this;
    }/**
     * 设置日志分类
     * @param  string $level 日志分类
     * @return obj           对象本身
     */
    public function cate($cate){
        if(in_array($cate, self::CATES)){
            $this->_cate = $cate;
        }
        return $this;
    }
    /**
     * 连续方法
     * @param  string $name   方法名
     * @param  array $params  参数
     * @return obj            对象本身
     */
    public function __call($name, $params)
    {

    	if(in_array($name, self::CATES)){
            return $this->cate($name);
    	}
        if(in_array($name, self::LEVELS)){
            return $this->level($name);
        }
        parent::__call($name, $params);
    }

    protected function getIp(){
    	if(strncmp(PHP_OS, 'WIN', 3) === 0){
    		$str = exec('ipconfig | findstr IPv4');
    		$ip = trim(strstr($str, ':'), ': ');
    	}else{
    		$ip = exec("ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d 'addr:'");
    	}
    	return $ip;
    }

    public function behaviors (){
        // return [LogBehavior::class];
        return [[
            'class' => LogBehavior::class,
            'encoding' => 'json',
        ]];
    }
}


